<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="配置名称" prop="configName">
        <el-input v-model="queryParams.configName" placeholder="请输入配置名称" clearable style="width: 240px" @keyup.enter="handleQuery"/>
      </el-form-item>
      <el-form-item label="存储类型" prop="storageType">
        <el-select v-model="queryParams.storageType" placeholder="存储类型" clearable style="width: 240px">
          <el-option label="本地存储" value="local"/>
          <el-option label="MinIO" value="minio"/>
          <el-option label="阿里云OSS" value="aliyun"/>
          <el-option label="腾讯云COS" value="tencent"/>
          <el-option label="AWS S3" value="aws"/>
        </el-select>
      </el-form-item>
      <el-form-item label="状态" prop="status">
        <el-select v-model="queryParams.status" placeholder="状态" clearable style="width: 240px">
          <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value"/>
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['file:storage:add']">新增
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate" v-hasPermi="['file:storage:edit']">修改</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete" v-hasPermi="['file:storage:remove']">删除
        </el-button>
      </el-col>
      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table v-loading="loading" :data="storageList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center"/>
      <el-table-column label="配置ID" align="center" prop="configId" width="80"/>
      <el-table-column label="配置名称" align="center" prop="configName" :show-overflow-tooltip="true"/>
      <el-table-column label="存储类型" align="center" prop="storageType" width="200">
        <template #default="scope">
          <el-tag v-if="scope.row.storageType === 'local'" type="danger">本地存储</el-tag>
          <el-tag v-else-if="scope.row.storageType === 'minio'" type="primary">MinIO</el-tag>
          <el-tag v-else-if="scope.row.storageType === 'aliyun'" type="success">阿里云OSS</el-tag>
          <el-tag v-else-if="scope.row.storageType === 'tencent'" type="info">腾讯云COS</el-tag>
          <el-tag v-else-if="scope.row.storageType === 'aws'" type="warning">AWS S3</el-tag>
          <el-tag v-else>{{ scope.row.storageType }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="访问地址" align="center" prop="endpoint" :show-overflow-tooltip="true"/>
      <el-table-column label="存储桶" align="center" prop="bucketName"/>
      <el-table-column label="HTTPS" align="center" prop="isHttps" width="80">
        <template #default="scope">
          <el-tag :type="scope.row.isHttps === 1 ? 'success' : 'info'" size="small">
            {{ scope.row.isHttps === 1 ? '是' : '否' }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column label="默认配置" align="center" prop="isDefault" width="100">
        <template #default="scope">
          <el-switch v-model="scope.row.isDefault" :active-value="1" :inactive-value="0" @change="handleSetDefault(scope.row)" :disabled="scope.row.status === 0"/>
        </template>
      </el-table-column>
      <el-table-column label="直传功能" align="center" prop="enableDirectUpload" width="100">
        <template #default="scope">
          <el-tag :type="scope.row.enableDirectUpload === 1 ? 'success' : 'info'" size="small">
            {{ scope.row.enableDirectUpload === 1 ? '是' : '否' }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column label="状态" align="center" prop="status" width="100">
        <template #default="scope">
          <el-switch v-model="scope.row.status" :active-value="1" :inactive-value="0" @change="handleStatusChange(scope.row)"/>
        </template>
      </el-table-column>
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
        <template #default="scope">
          <span>{{ parseTime(scope.row.createTime) }}</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" width="300" class-name="small-padding fixed-width">
        <template #default="scope">
          <el-button link type="primary" icon="View" @click="handleTest(scope.row)" v-hasPermi="['file:storage:test']" v-if="scope.row.storageType !== 'local'">测试</el-button>
          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['file:storage:edit']">修改</el-button>
          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['file:storage:remove']" v-if="scope.row.storageType !== 'local'">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList"/>

    <!-- 添加或修改存储配置对话框 -->
    <el-dialog :title="title" v-model="open" width="600px" append-to-body>
      <el-form ref="storageRef" :model="form" :rules="rules" label-width="120px">
        <el-form-item label="配置名称" prop="configName">
          <el-input v-model="form.configName" placeholder="请输入配置名称"/>
        </el-form-item>
        <el-form-item label="存储类型" prop="storageType">
          <el-select v-model="form.storageType" placeholder="请选择存储类型" style="width: 100%" @change="handleStorageTypeChange">
            <el-option label="本地存储" value="local"/>
            <el-option label="MinIO" value="minio"/>
            <el-option label="阿里云OSS" value="aliyun"/>
            <el-option label="腾讯云COS" value="tencent"/>
            <el-option label="AWS S3" value="aws"/>
          </el-select>
        </el-form-item>
        <el-form-item label="访问地址" prop="endpoint" v-if="form.storageType !== 'local'">
          <el-input v-model="form.endpoint" :placeholder="getEndpointPlaceholder()"/>
        </el-form-item>
        <el-form-item v-if="form.storageType === 'local'">
          <el-alert title="本地存储说明" type="info" :closable="false" show-icon>
            <template #default>
              本地文件存储根目录已在服务器配置文件中设置，无需手动配置访问地址。
              <br>当前配置路径：<code>ruoyi.file.local-storage-path</code>
            </template>
          </el-alert>
        </el-form-item>
        <el-form-item label="访问密钥" prop="accessKey" v-if="form.storageType !== 'local'">
          <el-input v-model="form.accessKey" placeholder="请输入访问密钥"/>
        </el-form-item>
        <el-form-item label="私有密钥" prop="secretKey" v-if="form.storageType !== 'local'">
          <el-input v-model="form.secretKey" type="password" placeholder="请输入私有密钥" show-password/>
        </el-form-item>
        <el-form-item label="存储桶名称" prop="bucketName">
          <el-input v-model="form.bucketName" :placeholder="getBucketPlaceholder()"/>
          <div class="el-form-item__tip" v-if="form.storageType === 'local'">
            本地存储目录名称，将在根目录下创建此目录
          </div>
        </el-form-item>
        <el-form-item label="区域" prop="region" v-if="form.storageType !== 'local'">
          <el-input v-model="form.region" placeholder="请输入区域，如：us-east-1"/>
        </el-form-item>
        <el-form-item label="自定义域名" prop="domain">
          <el-input v-model="form.domain" placeholder="请输入自定义域名（可选），例如：https://file.jiangyinda.com"/>
        </el-form-item>

        <!-- 配置选项区域 -->
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="启用HTTPS" prop="isHttps">
              <el-switch v-model="form.isHttps" :active-value="1" :inactive-value="0" active-text="是" inactive-text="否"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="启用直传" prop="enableDirectUpload">
              <el-switch v-model="form.enableDirectUpload" :active-value="1" :inactive-value="0" active-text="是" inactive-text="否" :disabled="form.storageType === 'local'"/>
              <div class="el-form-item__tip" v-if="form.storageType === 'local'" style="margin-top: 4px;">
                本地存储不支持前端直传
              </div>
            </el-form-item>
          </el-col>
        </el-row>

        <el-form-item label="令牌过期时间" prop="tokenExpireTime" v-if="form.enableDirectUpload === 1 || form.enableDirectUpload === '1'">
          <el-input-number v-model="form.tokenExpireTime" :min="300" :max="86400" placeholder="秒" style="width: 100%"/>
          <div class="el-form-item__tip">单位：秒，建议设置为 3600（1小时），范围300-86400秒</div>
        </el-form-item>
        <el-form-item label="最大文件大小" prop="maxFileSize">
          <el-row :gutter="15" style="width: 100%;">
            <el-col :span="16">
              <el-input-number v-model="fileSizeValue" :min="1" :max="1024" placeholder="文件大小" style="width: 100%"/>
            </el-col>
            <el-col :span="8">
              <el-select v-model="fileSizeUnit" placeholder="单位" style="width: 100%">
                <el-option label="KB" value="KB"/>
                <el-option label="MB" value="MB"/>
                <el-option label="GB" value="GB"/>
              </el-select>
            </el-col>
          </el-row>
        </el-form-item>
        <el-form-item label="允许文件类型" prop="allowedFileTypes">
          <el-input v-model="form.allowedFileTypes" type="textarea" placeholder="请输入允许的文件类型，如：.jpg,.png,.pdf"/>
          <div class="el-form-item__tip">用英文逗号分隔，如：.jpg,.png,.pdf，留空表示不限制</div>
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" type="textarea" placeholder="请输入备注"/>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup name="StorageConfig">
import {
  addStorageConfig,
  changeStorageConfigStatus,
  delStorageConfig,
  getStorageConfig,
  listStorageConfig,
  setDefaultStorageConfig,
  testStorageConfig,
  updateStorageConfig
} from "@/api/filemanager/storage"
import {refreshFileConfigCache} from '@/store/modules/fileConfig'

const {proxy} = getCurrentInstance()
const {sys_normal_disable, sys_yes_no} = proxy.useDict("sys_normal_disable", "sys_yes_no")

const storageList = ref([])
const open = ref(false)
const loading = ref(true)
const showSearch = ref(true)
const ids = ref([])
const single = ref(true)
const multiple = ref(true)
const total = ref(0)
const title = ref("")

// 文件大小相关
const fileSizeValue = ref(100)
const fileSizeUnit = ref('MB')

const data = reactive({
  form: {},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    configName: undefined,
    storageType: undefined,
    status: undefined
  },
  rules: {
    configName: [{required: true, message: "配置名称不能为空", trigger: "blur"}],
    storageType: [{required: true, message: "存储类型不能为空", trigger: "change"}],
    endpoint: [{required: true, message: "访问地址不能为空", trigger: "blur"}],
    bucketName: [{required: true, message: "存储桶名称不能为空", trigger: "blur"}]
  }
})

const {queryParams, form, rules} = toRefs(data)

/** 文件大小转换工具函数 */
// 将字节转换为友好显示的大小和单位
function bytesToSizeAndUnit(bytes) {
  if (!bytes) return {value: 100, unit: 'MB'}

  if (bytes >= 1024 * 1024 * 1024) {
    return {value: Math.round(bytes / (1024 * 1024 * 1024)), unit: 'GB'}
  } else if (bytes >= 1024 * 1024) {
    return {value: Math.round(bytes / (1024 * 1024)), unit: 'MB'}
  } else {
    return {value: Math.round(bytes / 1024), unit: 'KB'}
  }
}

// 将大小和单位转换为字节
function sizeAndUnitToBytes(value, unit) {
  if (!value) return 104857600 // 默认100MB

  switch (unit) {
    case 'KB':
      return value * 1024
    case 'MB':
      return value * 1024 * 1024
    case 'GB':
      return value * 1024 * 1024 * 1024
    default:
      return value * 1024 * 1024 // 默认MB
  }
}

/** 查询存储配置列表 */
function getList() {
  loading.value = true
  listStorageConfig(queryParams.value).then(response => {
    storageList.value = response.rows
    total.value = response.total
    loading.value = false
  })
}

/** 取消按钮 */
function cancel() {
  open.value = false
  reset()
}

/** 表单重置 */
function reset() {
  form.value = {
    configId: undefined,
    configName: undefined,
    storageType: undefined,
    endpoint: undefined,
    accessKey: undefined,
    secretKey: undefined,
    bucketName: undefined,
    region: undefined,
    isHttps: 1,
    domain: undefined,
    enableDirectUpload: '1',
    tokenExpireTime: 3600,
    maxFileSize: 104857600,
    allowedFileTypes: undefined,
    isDefault: 0,
    remark: undefined
  }
  // 重置文件大小显示
  fileSizeValue.value = 100
  fileSizeUnit.value = 'MB'
  proxy.resetForm("storageRef")
}

/** 搜索按钮操作 */
function handleQuery() {
  queryParams.value.pageNum = 1
  getList()
}

/** 重置按钮操作 */
function resetQuery() {
  proxy.resetForm("queryRef")
  handleQuery()
}

/** 多选框选中数据 */
function handleSelectionChange(selection) {
  ids.value = selection.map(item => item.configId)
  single.value = selection.length != 1
  multiple.value = !selection.length
}

/** 新增按钮操作 */
function handleAdd() {
  reset()
  open.value = true
  title.value = "添加存储配置"
}

/** 修改按钮操作 */
function handleUpdate(row) {
  reset()
  const configId = row.configId || ids.value
  getStorageConfig(configId).then(response => {
    form.value = response.data
    // 转换文件大小显示
    const sizeInfo = bytesToSizeAndUnit(response.data.maxFileSize)
    fileSizeValue.value = sizeInfo.value
    fileSizeUnit.value = sizeInfo.unit
    open.value = true
    title.value = "修改存储配置"
  })
}

/** 提交按钮 */
function submitForm() {
  proxy.$refs["storageRef"].validate(valid => {
    if (valid) {
      // 转换文件大小为字节
      const formData = {...form.value}
      formData.maxFileSize = sizeAndUnitToBytes(fileSizeValue.value, fileSizeUnit.value)

      if (form.value.configId != undefined) {
        updateStorageConfig(formData).then(async response => {
          proxy.$modal.msgSuccess("修改成功")
          open.value = false
          getList()
          // 刷新文件配置缓存
          await refreshFileConfigCache()
        })
      } else {
        addStorageConfig(formData).then(async response => {
          proxy.$modal.msgSuccess("新增成功")
          open.value = false
          getList()
          // 刷新文件配置缓存
          await refreshFileConfigCache()
        })
      }
    }
  })
}

/** 删除按钮操作 */
function handleDelete(row) {
  const configIds = row.configId || ids.value
  proxy.$modal.confirm('是否确认删除存储配置编号为"' + configIds + '"的数据项？').then(function () {
    return delStorageConfig(configIds)
  }).then(async () => {
    getList()
    proxy.$modal.msgSuccess("删除成功")
    // 使用统一的缓存刷新方法
    await refreshFileConfigCache()
  }).catch(() => {
  })
}

/** 状态切换处理 */
function handleStatusChange(row) {
  const statusText = row.status === 1 ? '启用' : '停用'
  const originalStatus = row.status === 1 ? 0 : 1 // 记录原始状态

  // 使用专门的状态修改接口
  const statusData = {
    configId: row.configId,
    status: row.status
  }

  // 如果是启用非本地存储，后端会自动进行测试
  if (row.status === 1 && row.storageType !== 'local') {
    proxy.$modal.loading("正在测试连接...")
  }

  changeStorageConfigStatus(statusData).then(async response => {
    try {
      if (row.status === 1 && row.storageType !== 'local') {
        proxy.$modal.closeLoading()
      }
      proxy.$modal.msgSuccess(`${statusText}成功`)

      // 先刷新列表，再刷新缓存，避免竞争条件
      await Promise.all([
        new Promise(resolve => {
          getList()
          resolve()
        }),
        refreshFileConfigCache()
      ])
    } catch (cacheError) {
      console.warn('缓存刷新失败:', cacheError)
      // 缓存刷新失败不影响主要功能，只是记录警告
    }
  }).catch((error) => {
    if (row.status === 1 && row.storageType !== 'local') {
      proxy.$modal.closeLoading()
    }
    // 操作失败，恢复开关状态
    row.status = originalStatus
    // 显示后端返回的错误信息
    const errorMsg = error.response?.data?.msg || `${statusText}失败`
    proxy.$modal.msgError(errorMsg)
  })
}

/** 设置默认配置 */
function handleSetDefault(row) {
  if (row.isDefault === 1) {
    setDefaultStorageConfig(row.configId).then(async () => {
      proxy.$modal.msgSuccess("设置默认配置成功")
      getList()
      // 使用统一的缓存刷新方法
      await refreshFileConfigCache()
    }).catch(() => {
      row.isDefault = 0
    })
  } else {
    proxy.$modal.msgWarning("只能设置为默认配置")
    row.isDefault = 1
  }
}

/** 测试连接 */
function handleTest(row) {
  proxy.$modal.loading("正在测试连接...")
  testStorageConfig(row).then(response => {
    proxy.$modal.closeLoading()
    proxy.$modal.msgSuccess("连接测试成功")
  }).catch(() => {
    proxy.$modal.closeLoading()
  })
}

/** 存储类型变化处理 */
function handleStorageTypeChange(value) {
  // 重置相关字段
  if (value === 'local') {
    form.value.endpoint = ''  // 本地存储不需要endpoint
    form.value.accessKey = ''
    form.value.secretKey = ''
    form.value.region = ''
    form.value.enableDirectUpload = 0
    form.value.isHttps = 0
  } else {
    form.value.enableDirectUpload = 1
    form.value.isHttps = 1
  }

  // 更新验证规则
  updateValidationRules(value)
}

/** 更新验证规则 */
function updateValidationRules(storageType) {
  if (storageType === 'local') {
    // 本地存储不需要endpoint、访问密钥和区域
    data.rules = {
      configName: [{required: true, message: "配置名称不能为空", trigger: "blur"}],
      storageType: [{required: true, message: "存储类型不能为空", trigger: "change"}],
      bucketName: [{required: true, message: "存储桶名称不能为空", trigger: "blur"}]
    }
  } else {
    // 其他存储类型需要完整配置
    data.rules = {
      configName: [{required: true, message: "配置名称不能为空", trigger: "blur"}],
      storageType: [{required: true, message: "存储类型不能为空", trigger: "change"}],
      endpoint: [{required: true, message: "访问地址不能为空", trigger: "blur"}],
      accessKey: [{required: true, message: "访问密钥不能为空", trigger: "blur"}],
      secretKey: [{required: true, message: "私有密钥不能为空", trigger: "blur"}],
      bucketName: [{required: true, message: "存储桶名称不能为空", trigger: "blur"}],
      region: [{required: true, message: "区域不能为空", trigger: "blur"}]
    }
  }
}

/** 获取端点占位符 */
function getEndpointPlaceholder() {
  switch (form.value.storageType) {
    case 'local':
      return '请输入存储根目录，如：/uploads 或 uploads'
    case 'minio':
      return '请输入MinIO访问地址，如：http://localhost:9000'
    case 'aliyun':
      return '请输入阿里云OSS访问地址，如：https://oss-cn-chengdu.aliyuncs.com'
    case 'tencent':
      return '请输入腾讯云COS访问地址，如：https://cos.ap-beijing.myqcloud.com'
    case 'aws':
      return '请输入AWS S3访问地址，如：https://s3.amazonaws.com'
    default:
      return '请输入访问地址'
  }
}

/** 获取桶名占位符 */
function getBucketPlaceholder() {
  switch (form.value.storageType) {
    case 'local':
      return '请输入目录名称，如：default'
    default:
      return '请输入存储桶名称'
  }
}

getList()
</script>

<style scoped>
.el-form-item__tip {
  color: #909399;
  font-size: 12px;
  line-height: 1.4;
  margin-top: 4px;
}


/* 调整滑块布局 */
.el-row .el-form-item {
  margin-bottom: 18px;
}

.el-row .el-form-item .el-form-item__label {
  font-size: 13px;
  font-weight: 500;
}

/* 滑块样式优化 */
.el-row .el-switch {
  margin-top: 2px;
}

.el-row .el-switch__label {
  font-size: 12px;
  color: #606266;
}
</style>
